package me.zhengjie.ppService;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.pojo.InBoundInfo;
import me.zhengjie.pojo.OutBoundOrderAllowResp;
import me.zhengjie.pojo.PPOutBoundParameter;
import me.zhengjie.pojo.PPWarningResp;
import me.zhengjie.pojo.sqlServer.PPInfo;
import me.zhengjie.pojo.sqlServer.PPInventory;
import me.zhengjie.pojo.sqlServer.PPTimeConfig;
import me.zhengjie.repository.PPInfoRepository;
import me.zhengjie.repository.PPInventoryRepository;
import me.zhengjie.repository.PPTimeConfigRepository;
import me.zhengjie.repository.PpPalletRepository;
import me.zhengjie.service.PPInfoService;
import me.zhengjie.service.PPStorageService;
import me.zhengjie.service.dto.PPTimeConfigDto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.transaction.Transactional;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author: xinglin
 * @CreateTime: 2024-08-03
 * @Description:
 * @Version: 1.0
 */

@Slf4j
@Component
@RequiredArgsConstructor
public class PPInventoryService {

    private final PPInventoryRepository ppInventoryRepository;

    private final PPTimeConfigRepository ppTimeConfigRepository;
    private final PPStorageService ppStorageService;

    private static final Logger ppLog = LoggerFactory.getLogger("pp");
    private final PpPalletRepository ppPalletRepository;


    /**
     * 保存PP库存
     *
     * @param inBoundInfo
     */
    @Transactional
    public void savePPInventory(InBoundInfo inBoundInfo,PPInfo ppInfo , String storageCode) {
        try {
            //先校验数据
            if (ObjectUtil.isEmpty(inBoundInfo.getPalletCode())) {
                throw new RuntimeException("托盘码不能为空");
            }
            if (ObjectUtil.isEmpty(inBoundInfo.getStationCode())) {
                throw new RuntimeException("工作站码不能为空");
            }
            if (ObjectUtil.isEmpty(inBoundInfo.getIsPackage())) {
                throw new RuntimeException("是否打包不能为空");
            }
            if (ObjectUtil.isEmpty(storageCode)) {
                throw new RuntimeException("库位不能为空");
            }

            //先判断库存中有没有这个pp，有则更新，没有则新增
            if (ppInventoryRepository.findByPpBatch(ppInfo.getPpBatch()) != null) {

                PPInventory ppInventory = ppInventoryRepository.findByPpBatch(ppInfo.getPpBatch());

                //查看数量是否为0，为0则删除
                if (ppInventory.getQty() <= 0) {
                    //如果输入的数量小于等于0，抛出异常
                    throw new RuntimeException("请使用空载盘");
                }

                //更新数量
                ppInventory.setQty(ppInfo.getPpQty());

//                //更新预警时间和报警时间
//                LocalDateTime now = LocalDateTime.now();
//                LocalDateTime outBoundTime = ppInventory.getOutBoundTime();
//                Duration duration = Duration.between(outBoundTime, now);
//                LocalDateTime warningTime = ppInventory.getWarningTime();
//                LocalDateTime alarmTime = ppInventory.getOutTime();
//                ppInventory.setWarningTime(warningTime.plus(duration));
//                ppInventory.setOutTime(alarmTime.plus(duration));

                //是否打包和更改在库状态为在库,以及更新载盘码
                ppInventory.setIsPakage(inBoundInfo.getIsPackage());
                ppInventory.setPalletCode(inBoundInfo.getPalletCode());

                //设置在库状态为在库（0为在库，1为出库）
                ppInventory.setStayStatus(0);
                //设置库存锁定状态为启用（0为禁用，1为启用）
                ppInventory.setLockStatus(1);
                ppInventoryRepository.save(ppInventory);

            } else {
                PPInventory ppInventory = new PPInventory();
                ppInventory.setBatch(ppInfo.getBatch());
                ppInventory.setPp(ppInfo.getPp());
                ppInventory.setPpBatch(ppInfo.getPpBatch());
                ppInventory.setPalletCode(inBoundInfo.getPalletCode());
                ppInventory.setStorageCode(storageCode);
                ppInventory.setInBoundTime(LocalDateTime.now());
                ppInventory.setQty(ppInfo.getPpQty());
                ppInventory.setIsPakage(inBoundInfo.getIsPackage());

                LocalDateTime now = LocalDateTime.now();
//                //默认是预警时间72,超期时间是96小时
//                int warningHours = ppTimeConfigRepository.findByPpBatch(ppInfo.getPpBatch()).getWarningTime();
//                int alarmHours = ppTimeConfigRepository.findByPpBatch(ppInfo.getPpBatch()).getAlarmTime();

                //以打包时间为准,打包前24预警，超过打包就报警
//                ppInventory.setWarningTime(ppInfo.getPpPd().plusHours(warningHours));
//                ppInventory.setOutTime(ppInfo.getPpPd().plusHours(alarmHours));

                ppInventory.setWarningTime(ppInfo.getPpPack().minusHours(24));
                ppInventory.setOutTime(ppInfo.getPpPack());
                ppInventory.setPdTime(ppInfo.getPpPd());
                ppInventory.setExpTime(ppInfo.getPpExp());
                ppInventory.setDateStatus("safe");
                //设置库存在库状态为在库
                ppInventory.setStayStatus(0);
                //设置库存锁定状态为启用
                ppInventory.setLockStatus(1);
                ppInventoryRepository.save(ppInventory);
            }

        } catch (Exception e) {
            ppLog.error("保存PP库存失败", e);
        }
    }





    /**
     * 更新pp状态
     */
    @Transactional
    public void updateStayStatus() {
        //查找所有没有打包的库存
        List<PPInventory> NoPakageList = ppInventoryRepository.findAll().stream().filter(item -> item.getIsPakage() == 0).collect(Collectors.toList());
        //查找所有打包的库存
        List<PPInventory> PakageList = ppInventoryRepository.findAll().stream().filter(item -> item.getIsPakage() == 1).collect(Collectors.toList());

        LocalDateTime now = LocalDateTime.now();
        //设置没有打包的库存状态
        NoPakageList.forEach(item -> {
                    // 如果当前时间在警告时间之前
                    if (now.isBefore(item.getWarningTime())) {
                        // 设置日期状态为安全
                        item.setDateStatus("safe");
                    } else if ((now.isAfter(item.getWarningTime()) || now.equals(item.getWarningTime())) && now.isBefore(item.getOutTime())) {
                        // 如果当前时间在警告时间和过期时间之间
                        // 设置日期状态为警告
                        item.setDateStatus("warning");
                    } else if (now.isAfter(item.getOutTime()) || now.equals(item.getOutTime())) {
                        // 如果当前时间在过期时间之后
                        // 设置日期状态为过期
                        item.setDateStatus("outTime");
                    }

                    if (now.isAfter(item.getExpTime()) || now.equals(item.getExpTime())) {
                        // 如果当前时间在商品过期时间之后，或者当前时间等于商品过期时间
                        // 商品状态设置为过期
                        item.setDateStatus("exp");
                    }
                }
        );


        // 遍历商品列表
        PakageList.forEach(item -> {
                    // 获取商品的过期时间
                    //要在过期时间前一一天预警
                    LocalDateTime expTime = item.getExpTime().minusHours(24);

                    // 如果当前时间在商品过期时间之前

                    if (now.isBefore(expTime)) {
                        // 商品状态设置为安全
                        item.setDateStatus("safe");
                    } else if (now.isAfter(expTime) || now.equals(expTime)) {
                        // 如果当前时间在商品过期时间之后，或者当前时间等于商品过期时间
                        // 商品状态设置为过期
                        item.setDateStatus("exp");
                    }

                }
        );

        ppInventoryRepository.saveAll(NoPakageList);
        ppInventoryRepository.saveAll(PakageList);

    }


    public List<PPWarningResp> getPPWarningResp() {
        List<PPWarningResp> ppWarningRespList = new ArrayList<>();
        //过滤出不正常的
        List<PPInventory> ppInventoryList = ppInventoryRepository.findAll().stream().filter(item -> !item.getDateStatus().equals("safe")).collect(Collectors.toList());
        //再过滤出在库存里的
        ppInventoryList = ppInventoryList.stream().filter(item -> item.getStayStatus() == 0).collect(Collectors.toList());
        //封装异常的pp状态传给前端
        ppInventoryList.forEach(item -> {

            PPWarningResp ppWarningResp = new PPWarningResp();
            // 如果item中的ppBatch和dateStatus不为空
            if (item.getPpBatch() != null && item.getDateStatus() != null) {
                // 将item中的ppBatch和dateStatus设置到ppWarningResp中
                ppWarningResp.setPpBatch(item.getPpBatch());
                ppWarningResp.setDateStatus(item.getDateStatus());
            }
            // 将ppWarningResp添加到ppWarningRespList中
            ppWarningRespList.add(ppWarningResp);
        });
        return ppWarningRespList;
    }


    @Transactional
    public void outBoundByPalletCode(String palletCode) {

        PPInventory ppInventory = ppInventoryRepository.findPPInventoryByPalletCode(palletCode);

        // 设置库存状态为1（出库）
        ppInventory.setStayStatus(1);
        // 设置出库时间为当前时间
        ppInventory.setOutBoundTime(LocalDateTime.now());
        // 设置托盘码为空，避免库存出现相同的载盘码，导致查询库存信息出错
        ppInventory.setPalletCode(null);
        ppInventoryRepository.save(ppInventory);

//        if (ppInventory.getIsPakage()==0){
//         //该托盘未打包，不能删除,设置为出库状态。使用完之后会返回库存
//            ppInventory.setStayStatus(1);
//            ppInventory.setOutBoundTime(LocalDateTime.now());
//            ppInventoryRepository.save(ppInventory);
//
//        }else {
//            //如果打包过则是直接计算过期时间，要使用直接删除库存
//           ppInventoryRepository.deletePPInventoryByPalletCode(palletCode);

//        }

    }

    //判断pp库存是否存在
    public boolean isExist(String ppBatch) {
        //查询pp库存中是否存在该批次
        if (BeanUtil.isEmpty(ppInventoryRepository.findByPpBatch(ppBatch)))  {
            return false;
        } else {
            return true;
        }
    }


    /**
     * 判断出库单中的的pp库存是否锁定或者已经出库
     *
     * @param parameters
     * @return
     */
    public OutBoundOrderAllowResp OutBoundOrderAllow(List<PPOutBoundParameter> parameters) {
        Boolean allow = true;
        List<String> ppBatchs = new ArrayList<>();
        for (PPOutBoundParameter x : parameters) {
            PPInventory ppInventory = ppInventoryRepository.findByPpBatch(x.getPpBatch());
            //当库存锁定或者库存在库状态为1（出库）时，不允许出库，返回异常的pp批次号
            if (ppInventory.getLockStatus() == 0 || ppInventory.getStayStatus() == 1) {
                ppBatchs.add(ppInventory.getPpBatch());
                allow = false;
            }

        }
        // 创建OutBoundOrderAllowResp对象
        OutBoundOrderAllowResp outBoundOrderAllowResp = new OutBoundOrderAllowResp();
        // 设置允许出库标志
        outBoundOrderAllowResp.setAllow(allow);
        // 设置批次信息
        outBoundOrderAllowResp.setPpBatchs(ppBatchs);

        return outBoundOrderAllowResp;

    }

    /**
     * 更改pp的预警或超期时间
     */
    @Transactional
    public void updatePPTimeConfig(PPTimeConfigDto ppTimeConfigdto) {
        //更新config的时间

        //根据ppBatch从ppTimeConfigRepository中查找旧的ppTimeConfig
        PPTimeConfig oldppTimeConfig = ppTimeConfigRepository.findByPpBatch(ppTimeConfigdto.getPpBatch());
        //根据ppBatch从ppInventoryRepository中查找ppInventory
        PPInventory ppInventory = ppInventoryRepository.findByPpBatch(ppTimeConfigdto.getPpBatch());
        //如果ppTimeConfigdto中的预警时间或超期时间不为空，则更新ppInventory中的预警时间或超期时间
        if (ppTimeConfigdto.getWarningTime() != null) {
           int warningDiff = oldppTimeConfig.getWarningTime() - ppTimeConfigdto.getWarningTime();
            ppInventory.setWarningTime(ppInventory.getWarningTime().minusHours(warningDiff));
            oldppTimeConfig.setWarningTime(ppTimeConfigdto.getWarningTime());
        }
        if (ppTimeConfigdto.getAlarmTime() != null) {
           int alarmDiff = oldppTimeConfig.getAlarmTime() - ppTimeConfigdto.getAlarmTime();
            ppInventory.setOutTime(ppInventory.getOutTime().minusHours(alarmDiff));
            oldppTimeConfig.setAlarmTime(ppTimeConfigdto.getAlarmTime());
        }

        ppTimeConfigRepository.save(oldppTimeConfig);
        ppInventoryRepository.save(ppInventory);


    }


    public List<String> getPpBatchRandom() {
       List<PPInventory> ppInventoryList =   ppInventoryRepository.findAll()
               .stream().filter(im->im.getStayStatus()==0).collect(Collectors.toList());

       //随机截取俩个作为一一个新的ppInventoryList
       List<PPInventory> randomList = ppInventoryList.stream().skip((int) (Math.random() * ppInventoryList.size())).limit(2).collect(Collectors.toList());

       List<String> ppBatchList = randomList.stream().map(PPInventory::getPpBatch).collect(Collectors.toList());

       return ppBatchList;

    }


    @Transactional
    public void refeaseInventory(PPInventory ppInventory) {
        ppInventory.setLockStatus(1);
        ppInventory.setStayStatus(0);
        ppInventoryRepository.save(ppInventory);
    }


    //手动出库
    @Transactional
    public void manualOutbound(int id) {

        PPInventory ppInventory = ppInventoryRepository.findPPInventoryById(id);

        // 释放储位
        ppStorageService.cleanStorage(ppInventory.getStorageCode());

        //更新库存状态
        String palletCode = ppInventory.getPalletCode();
        this.outBoundByPalletCode(palletCode);

        //解绑载盘，如果工作站类型是1就要把载盘也给删除
        ppPalletRepository.deleteByPalletCode(palletCode);

    }

}
